<?php
/**
 * appRain v 0.1.x
 *
 * LICENSE
 *
 * This source file is subject to the MIT license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.opensource.org/licenses/mit-license.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@apprain.com so we can send you a copy immediately.
 *
 * @copyright  Copyright (c) 2010 appRain, Team. (http://www.apprain.com)
 * @license    http://www.opensource.org/licenses/mit-license.php MIT license
 *
 * HELP
 *
 * Official Website
 * http://www.apprain.com/
 *
 * Download Link
 * http://www.apprain.com/download
 *
 * Documents Link
 * http ://www.apprain.com/docs
 */

class Component_Appstore_Helpers_Data extends appRain_Base_Objects
{
	const _minitem = 1;
	const _itemremovelimit = 0;
	const STATUS_PENDING = 'Pending';
	const STATUS_PROCESSING = 'Processing';
	const STATUS_COMPLETE = 'Complete';
	const STATUS_PAID = 'Paid';


	public  $enablepaymentprocessor = true;
	private $itemtotal = null;

    /**
     * Get Payment status in Array
     */
	public function getPaymentStatusList()
	{
		return Array(
			self::STATUS_PENDING=>self::STATUS_PENDING,
			self::STATUS_PAID=>self::STATUS_PAID
		);
	}

    /**
     * Get Delivery stats in Array
     */
	public function getDeliveryStatusList()
	{
		return Array(
			self::STATUS_PENDING=>self::STATUS_PENDING,
			self::STATUS_PROCESSING=>self::STATUS_PROCESSING,
			self::STATUS_COMPLETE=>self::STATUS_COMPLETE
		);
	}

    /**
     * Add Item
     */
	public function quickAdd($pid=null, $qty=null)
	{
		$this->cleartotalItem();

		if(!isset($pid) || !isset($qty))
		{
			throw new AppException($this->__("System error, Please try after a few moment."));
			return ;
		}

		$cartInfo = $this->getCartInfo();

		if($qty == self::_itemremovelimit) unset($cartInfo[$pid]);
		else $cartInfo[$pid] = (string) $qty;

		App::Module('Session')->write('appcart',$cartInfo);

		return $this;
	}
    /**
     *  Remove item from cart
     */
	public function removeItem($id=null)
	{
		$this->cleartotalItem();
		$cartInfo = $this->getCartInfo();

		if(isset($cartInfo[$id])) unset($cartInfo[$id]);

		App::Module('Session')->write('appcart',$cartInfo);
	}

    /**
     * Clear total item
     */
	public function cleartotalItem()
	{
		$this->itemtotal = null;
	}

    /**
     * Clear Cart from Session
     */
	public function clearcart()
	{
		$this->cleartotalItem();
		App::Module('Session')->delete('appcart');
		App::Module("Session")->delete("appOrderId");
	}

    /**
     * Get cart infor by product id
     */
	public function getCartInfoByProductId($id=null)
	{
		$cartInfo = App::Module('Session')->read('appcart');
		return isset($cartInfo[$id]) ? $cartInfo[$id] : self::_minitem;
	}

    /**
     * Get Cart Info
     */
	public function getCartInfo($pid = NULL)
	{
		$cartInfo = App::Module('Session')->read('appcart');

		if(isset($pid)) return isset($cartInfo[$pid]) ? $cartInfo[$pid] : null;
		else return empty($cartInfo) ? array() : $cartInfo;
	}

    /**
     * Get Total Item info
     */
	public function getCartTotalItem()
	{
		if(!isset($this->itemtotal))
		{
			$this->itemtotal = 0;
			foreach($this->getCartInfo() as $item)
			{
				$this->itemtotal += $item;
			}
		}
		return $this->itemtotal;
	}

    /**
     * Simple validation
     */
	public function isToCheckout()
	{
		return ($this->getCartTotalItem() > 0) ? true : false;
	}

    /**
     * Render Order Information
     */
	public function renderShoppingCart()
	{
		$currency = App::Helper('Config')->siteInfo('currency');

        $itemData = App::Module('Session')->read('iteminfo');

		$gandtotal = 0;
		$tqty = 0;
		$DataGrid = App::Module('DataGrid');
		foreach($this->getCartInfo() as $pid=> $qty)
		{if(isset($itemData[$pid])){

            $itminfo = $itemData[$pid];
            $str = App::Component('AppStore')->Helper('Product')->PersonalisedData('HTML',$itminfo,true);

			$tmp = Array();
			$product = App::InformationSet()->findById($pid);
			$tmp['title'] = $product['title'];
			$tmp['thumb'] = App::Helper('Html')->imgDTag(App::Helper('Config')->basedir("/uploads/filemanager/{$product['imagethumb']}"));
			$tmp['shortdesc'] = trim(strip_tags($product['shortdesc']));
			$tmp['qty'] = $qty;
			$tmp['price'] = "{$qty} x {$product['price']}";
			$tmp['subtotal'] = "{$currency} " . ($qty * $product['price']);
			$gandtotal += ($qty * $product['price']);
			$tqty += $qty;
            
            $catId = $product['category'];
			$DataGrid->addRow(
								App::Helper('Html')->linkTag(App::Helper("Config")->baseurl("/checkout/removeitem/{$pid}"),App::Helper('Html')->imgTag(App::Helper('Config')->baseurl('/images/admin/remove.gif'))) . 
                                App::Helper('Html')->linkTag(App::Helper("Config")->baseurl("/store-by-product/{$pid}|{$catId}"),App::Helper('Html')->imgTag(App::Helper('Config')->baseurl('/images/admin/edit.gif'))),
								$tmp['thumb'],
								//$tmp['title'],
								$str,
								//$tmp['qty'],
								$tmp['price'],
								$tmp['subtotal']
							  );
		}}

		$DataGrid->setHeader(Array("","","","Item Price","Sub Total"))
				 ->setFooter(Array("","","&nbsp;","&nbsp;","{$currency} {$gandtotal} (Total)"))
				 ->Render();
	}

    /**
     * Create HTML View of an Invoice
     */
	public function getInvoice($orderid=NULL)
	{
		if(!isset($orderid)) $orderid = $this->getOrderId();

		$currency = App::Helper('Config')->siteInfo('currency');

		$items = App::Model('Item')->findAllByOrderid($orderid);

		$gandtotal = 0;
		$tqty = 0;
		$DataGrid = App::Module('DataGrid');
		foreach($items['data'] as $val)
		{
			$pid = $val['productid'];
			$qty = $val['qty'];

			$tmp = Array();
			$product = App::InformationSet()->findById($pid);

			$tmp['title'] = $product['title'];
			$tmp['thumb'] = App::Helper('Html')->imgDTag(App::Helper('Config')->basedir("/uploads/filemanager/{$product['imagethumb']}"));
			$tmp['shortdesc'] = trim(strip_tags($product['shortdesc']));
			$tmp['qty'] = $qty;
			$tmp['price'] = "{$qty} x {$product['price']}";
			$tmp['subtotal'] = "{$currency} " . ($qty * $product['price']);
			$gandtotal += ($qty * $product['price']);
			$tqty += $qty;

			$DataGrid->addRow(
								$tmp['thumb'],
								$tmp['title'],
								$tmp['shortdesc'],
								$tmp['qty'],
								$tmp['price'],
								$tmp['subtotal']
							  );
		}
		
		$additionalData = $this->orderadditionalData($orderid,false);
		$totalItem = $this->totalOrderItem($orderid);
		$totalExpressCost = 0;
		$totalSignatureCost = 0;
		
		$nextdaydalivery = isset($additionalData['nextdaydalivery']) ? $additionalData['nextdaydalivery'] : 'No';
		$signature = isset($additionalData['signature']) ? $additionalData['signature'] : 'No';
		
		if(strtolower($nextdaydalivery) == 'yes')
		{
			$cost = App::Helper('Config')->siteInfo('appstore_next_delivery_cost');
			$totalExpressCost = ($totalItem * $cost);
			$DataGrid->addRow(
								"&nbsp;",
								"&nbsp;",
								"&nbsp;",
								"Express Delivery Cost",
								"&nbsp;",
								$totalExpressCost
							  );
		}

		if(strtolower($signature) == 'yes')
		{
			$cost = App::Helper('Config')->siteInfo('appstore_signature_cost');
			$totalSignatureCost = ($totalItem * $cost);
			$DataGrid->addRow(
								"&nbsp;",
								"&nbsp;",
								"&nbsp;",
								"Signature Cost",
								"&nbsp;",
								$totalSignatureCost
							  );
		}
		
		$gandtotal = ($gandtotal + $totalExpressCost + $totalSignatureCost);
							  
							  
		return  $DataGrid->setHeader(Array("","Name","Description","Quantity","Item Price","Sub Total"))
				         ->setFooter(Array("","","","{$tqty} (Total Qty)","&nbsp;","{$currency} {$gandtotal} (Total)"))
				         ->Render(true,Array("border"=>'1','width'=>'100%','cellspacing'=>'3','cellpadding'=>"3","bordercolor"=>"#E4802A"));
	}

    /**
     * Check if order exists in Database
     */
	public function isOrderExistsInDB($id)
	{
		$data = App::Model('Order')->findById($id);

		return !empty($data);
	}

    /**
     * Retrive order id
     */
	public function getOrderId()
	{
		$orderid = App::Module("Session")->Read("appOrderId");

		return (isset($orderid) && $this->isOrderExistsInDB($orderid)) ? $orderid : null;
	}

    /**
     * Register order id in Session
     */
	public function register($id=null)
	{
		if($this->getOrderId() === null)
		{
			App::Module("Session")->Write("appOrderId",$id);
		}

	}

    /**
     * Move first instance in database
     */
	private function moveOrderInstanceToDB()
	{
        $adata = $this->orderadditionalData(null,false);
		$obj = App::Model('Order')->setId($this->getOrderId())
								  ->setOrderdate(App::Helper('Date')->getDate())
                                  ->setAdditional(serialize($adata))   
								  ->Save();
		if($obj->getErrorInfo())
		{
			echo App::Module("Cryptography")->jsonEncode(array( "_status" =>"Error", "_message"=>$this->__('Invalid Order Post data')));
			exit;
		}
		else
		{
			$this->Register($obj->getId());
		}

		return $this;
	}

	public function orderData($orderId=null)
	{
		if(isset($orderId)) return App::Model('Order')->findById($orderId);

		return Array();
	}

	/**
	 * Order Aditional Data
	 */
	public function orderadditionalData($orderId=null,$isSerialize = true)
	{
		$result = Array();
       
		if(!isset($orderId))
		{
			$data = $this->getCheckoutPostData();
			$result = isset($data['Additional']) ? $data['Additional'] : Array();
		}
		else
		{
			$data = App::Model('Order')->findById($orderId);
           
			if($data['additional']!="")
			{
				$result = isset($data['additional']) ? unserialize($data['additional']) : Array();
			}
		}

		return ($isSerialize) ? serialize($result) : $result;
	}
	/**
	 * Order Total Item
	 */
	public function totalOrderItem($orderid=null)
	{
		if(isset($orderid))
		{
			$row = App::Model('Item')->find("orderid={$orderid}",null,'count(*) as cnt');
			return $row['cnt'];

		}
		else $this->getCartTotalItem();
	}

    /**
     * Move Items in Database
     */
	private function moveItemsToDB()
	{
		$cartinfo = $this->getCartInfo();
		$orderid = $this->getOrderId();

		$itemsindb = App::Model('Item')->findAllByOrderId($orderid);

		$clonecartinfo = $cartinfo;
		if(!empty($itemsindb['data']))
		{
			foreach($itemsindb['data'] as $item)
			{
				if(in_array($item['productid'],array_keys($clonecartinfo)))
				{
					$this->updateItemByPid($item['productid'],$item['id']);
					if(isset($clonecartinfo[$item['productid']]))unset($clonecartinfo[$item['productid']]);
				}
				else
				{
					App::Model('Item')->DeleteById($item['id']);
				}
			}
		}

		if(!empty($clonecartinfo))
		{
			foreach($clonecartinfo as $pid => $qty)
			{
				$this->updateItemByPid($pid);
			}
		}

		return $this;
	}

    /**
     * Update Item Information
     */
	private function updateItemByPid($pid=null,$itemid=null)
	{
		$product = App::InformationSet()->findById($pid);
        $pdata = App::Module('Session')->read('iteminfo');
        $perData = isset($pdata[$pid]) ? $pdata[$pid] : "";
		$_pdo=App::Model('Item')->setId($itemid)
								->setOrderid($this->getOrderId())
								->setProductid($pid)
								->setDated(App::Helper('Date')->getDate('Y-m-d H:i:s'))
								->setTitle($product['title'])
								->setUnitprice($product['price'])
								->setQty($this->getCartInfo($pid))
								->setTotalprice($product['price'] * $this->getCartInfo($pid))
								->setProductdata(serialize($perData))
								->setStatus(self::STATUS_PENDING)
								->Save();
	}

    /**
     * Calculate total Qty
     */
	public function totalQty($orderid=null)
	{
		if(!isset($orderid)) $orderid = $this->getOrderId();

		$data = App::Model('Item')->find(
                                            $condition   = "orderid={$orderid}",
                                            $from_clause = null,
                                            $from_string = "sum(qty) as total");

		return $data['total'];
	}

    /**
     * Calculate total Cost
     */
	public function totalCost($orderid=null)
	{
		if(!isset($orderid)) $orderid = $this->getOrderId();

		$data = App::Model('Item')->find(
                                                $condition   = "orderid={$orderid}",
                                                $from_clause = null,
                                                $from_string = "sum(totalprice) as total");

		$total = (round($data['total'],2) + $this->shippingCost($orderid) + $this->additionalPrice($orderid)) ;

		return $total;
	}

	public function shippingCost($orderId=null)
	{
		$orderData = $this->orderData($orderId);

		$shippingData = $this->getCheckoutPostData();

		if(isset($shippingData['Shipping']))
		{
			$countrycode = $shippingData['Shipping']['country'];
		}
		else
		{
			$orderData = unserialize($orderData['shippingaddress']);
			$countrycode = $orderData['country'];
		}

		$data = App::InformationSet('shippingcountry')->findByCode($countrycode);

		return isset($data['cost']) ? $data['cost'] : "0.00";
	}
	
	public function additionalPrice($orderid=null)
	{
		$additionalData = $this->orderadditionalData($orderid,false);
        
		$totalItem = $this->totalOrderItem($orderid);

		$totaladditionalcost = 0;

		$nextdaydalivery = isset($additionalData['nextdaydalivery']) ? $additionalData['nextdaydalivery'] : 'No';

		if(strtolower($nextdaydalivery) == 'yes')
		{
			$cost = App::Helper('Config')->siteInfo('appstore_next_delivery_cost');

			$totaladditionalcost += ($totalItem * $cost);
		}

		$signature = isset($additionalData['signature']) ? $additionalData['signature'] : 'No';

		if(strtolower($signature) == 'yes')
		{
			$cost = App::Helper('Config')->siteInfo('appstore_signature_cost');
			$totaladditionalcost += ($totalItem * $cost);
		}

		return $totaladditionalcost;
	}

    /**
     * Get Payment name from it's class
     */
	public function paymentMethodToStatusName($method)
	{
		try
        {
			return App::Component('appStore')->Helper("Pgateway_common")->getObject($method)->getStatusName();
		}
		catch(Exception $e)
		{
			return $method;
		}

	}

    /**
     * Update order data completely
     */
	public function completeOrderUpdate()
	{
		$orderid = $this->getOrderId();
		$shippingadd = $this->getShippingAddress();
		$billingadd = $this->getBillingAddress();

		$method = $this->paymentMethodToStatusName($this->getPaymentMethod());

		if(!isset($orderid))
		{
			echo App::Module("Cryptography")->jsonEncode(array( "_status" =>"Error", "_message"=>$this->__('Order Data is not formated')));
			exit;
		}
		else
		{
           // pre($this->totalCost());
			App::Model('Order')->setId($orderid)
							   ->setShippingaddress(serialize($shippingadd))
							   ->setBillingaddress(serialize($billingadd))
							   ->setPaymenttype($method)
							   ->setQty($this->totalQty())
							   ->setTotalcost($this->totalCost())
							   ->Save();
		}

	}

    /**
     * Change the order status
     * bydefault the status is set to "Paid" for payment success
     */
	public function ChnageOrderStatus($orderid=NULL,$status=null,$isnotified=true)
	{
		if(!isset($orderid)) $orderid = $this->getOrderId();

		$Payment = App::Component('appStore')->Helper("Pgateway_common")->getObject($this->getPaymentmethod());

		if(!isset($status)) $status =$Payment->paymentStatus();

		App::Model('Order')->setId($orderid)
						   ->setPaymentType($this->getPaymentType())
						   ->setPaymentstatus($status)
						   ->setDeliverystatus($Payment->shippingStatus())
						   ->Save();
		if($isnotified)
		{
			$this->sendOrderMail($orderid,$status);
		}

		return $this;
	}

    /**
     * Send order notification
     * Notification text fetch from Email Template edited by Admin
     * Email Template Keywords
     * {FirstName} {LastName} {AddressLine1} {AddressLine2}
     * {Email} {Invoice} {Phone} {City} {State} {Zipcode} {Country}
     */
	public function sendOrderMail($orderid=NULL,$status=self::STATUS_PAID)
	{
		if(!isset($orderid)) $orderid = $this->getOrderId();

		$orderData = App::Model('Order')->findById($orderid);
		$shippingaddress = unserialize($orderData['shippingaddress']);

		$params =
		Array(
			"FirstName" => $shippingaddress['fname'],
			"LastName" => $shippingaddress['lname'],
			"AddressLine1" => $shippingaddress['address_line_1'],
			"AddressLine2" => $shippingaddress['address_line_2'],
			"Email" => $shippingaddress['email'],
			"Invoice" => $this->getInvoice($orderid),
			"Phone" => "",
			"City" => $shippingaddress['city'],
			"State" => $shippingaddress['state'],
			"Zipcode" => $shippingaddress['zipcode'],
			"Country" => App::Helper('Utility')->CountryCodeToName($shippingaddress['country'])
		);

		if($status==self::STATUS_PAID)
		{
			App::Helper('EmailTemplate')->setParameters($params)
									    ->prepare('StorePaymentSuccessAdmin',true);
			App::Helper('EmailTemplate')->setParameters($params)
		                            ->setTo(Array("{$shippingaddress['email']}","{$shippingaddress['fname']} {$shippingaddress['lname']}"))
									->prepare('StorePaymentSuccessCustomer',true);
		}
		else
		{
			App::Helper('EmailTemplate')->setParameters($params)
									    ->prepare('StorePaymentFailedAdmin',true);

			App::Helper('EmailTemplate')->setParameters($params)
		                            ->setTo(Array("{$shippingaddress['email']}","{$shippingaddress['fname']} {$shippingaddress['lname']}"))
									->prepare('StorePaymentFailedCustomer',true);
		}
		//exit;
	}

    /**
     * Do more validation as per
     * Need
     */
    public function orderValidation()
    {
        if(!$this->isToCheckout())
        {
            echo App::Load("Module/Cryptography")->jsonEncode(array("_status" =>"Redirect","_location"=>App::Helper('Config')->baseUrl("/")));
            exit;
        }

		$this->verifyAddress()->verifyAddress('Shipping');

        return $this;
    }

	public function verifyAddress($type="Billing")
	{
		$address = ($type=="Billing") ? $this->getBillingAddress()
									  : $this->getShippingAddress();

		if(!App::Helper('Validation')->notEmpty($address['fname'])){echo App::Module("Cryptography")->jsonEncode(array( "_status" =>"Error", "_message"=>$this->__("Please enter {$type} First Name")));exit;}
		else if(!App::Helper('Validation')->notEmpty($address['lname'])){echo App::Module("Cryptography")->jsonEncode(array( "_status" =>"Error", "_message"=>$this->__("Please enter {$type} Last Name")));exit;}
		else if(!App::Helper('Validation')->notEmpty($address['address_line_1'])){echo App::Module("Cryptography")->jsonEncode(array( "_status" =>"Error", "_message"=>$this->__("Please enter {$type} address line 1")));exit;}
		else if(!App::Helper('Validation')->notEmpty($address['city'])){echo App::Module("Cryptography")->jsonEncode(array( "_status" =>"Error", "_message"=>$this->__("Please enter {$type} valid city")));exit;}
		else if(!App::Helper('Validation')->notEmpty($address['state'])){echo App::Module("Cryptography")->jsonEncode(array( "_status" =>"Error", "_message"=>$this->__("Please enter {$type} valid state")));exit;}
		else if(!App::Helper('Validation')->email($address['email'])){echo App::Module("Cryptography")->jsonEncode(array( "_status" =>"Error", "_message"=>$this->__("Please enter {$type} valid email address")));exit;}
		else if(!App::Helper('Validation')->notEmpty($address['country'])){echo App::Module("Cryptography")->jsonEncode(array( "_status" =>"Error", "_message"=>$this->__("Please enter {$type} valid select country")));exit;}

		return $this;
	}

	public function organiseResource()
	{
		$data = $this->getCheckoutPostData();
		$data['Checkout']['shiptobillingaddress'] = isset($data['Checkout']['shiptobillingaddress']) ? "Yes":"No";
		if($data['Checkout']['shiptobillingaddress'] == "Yes")
		{
			$data['Shipping'] = $data['Billing'];
		}

		$this->setShipToBillingAddress($data['Checkout']['shiptobillingaddress']);
		$this->setShippingAddress($data['Shipping']);
		$this->setBillingAddress($data['Billing']);
		$this->setPaymentMethod($data['Payment']['method']);
		$this->setPaymentData(isset($data['Payment'][$data['Payment']['method']]) ? $data['Payment'][$data['Payment']['method']] : Array());

		return $this;
	}

	public function StartCheckoutProcess()
	{
			 // Move first Instance
			 // of Quote in Data base
		$this->moveOrderInstanceToDB()
			 // Move/Update Items
			 // database
		     ->moveItemsToDB()
			 // Set Shipping address, Paymants method
			 // by maginc methods and the more full
			 // Order to database
			 //---------------------------------------+
			 ->completeOrderUpdate();


		if($this->enablepaymentprocessor)
		{
            // Instantiate payment process class and execute.
            // We always expect a class with the pattern of
            // "Pgateway_PaymentMethod" For example "Pgateway_Paypal".
            // This class will auto load from "development/helper/pgateway".
            // Each payment class must have a method place() that will
            // execute form this point and do other task as per need
            // and for any invalid operation throw a exception that will
            // will catch from base checkout call try block in completeCheckoutAction()
            // -----------------------------------------------------------------------+
			App::Component('appStore')->Helper("Pgateway_common")
							 ->getObject($this->getPaymentMethod())
			                 ->setPaymentData($this->getPaymentData())
							 ->setAmount($this->totalCost())
							 ->setOrderId($this->getOrderId())
							 ->setBillingAddress($this->getBillingAddress())
							 ->place();
		}

		return $this;
	}
}